﻿
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel.Composition;


namespace DailyFx.UI
{

	public interface IMenu : IUICommand, IUIDisplayText, IUIStatus, IUIChild, INotifyPropertyChangedEx
	{ // As a Matter of Fact, this is a Menu Item

		/// <summary>
		///		Display text .
		/// </summary>
		// string Text { get; }

		/// <summary>
		///		UI Icon file, Maybe a thumbnail image .
		/// </summary>
		string Icon { get; }

		/// <summary>
		///		Short-Cut Gesture .
		/// </summary>
		string HotKey { get; }


		/// <summary>
		///		Checkable Style .
		/// </summary>
		bool CanCheck { get; }

		/// <summary>
		/// 
		/// </summary>
		bool IsChecked	{ get; set; }

		/// <summary>
		///		a.k.a seperator .
		/// </summary>
		bool IsDivider { get; }

		/// <summary>
		///		Indicates the visibility of this UI Element .
		/// </summary>
		bool Visibility { get; }

		/// <summary>
		///		Sub Menu Item(s) .
		/// </summary>
		IBindableCollection<IMenu> Children { get; }
	
		
		/// <summary>
		///		Hosted by a parent UI Control .
		/// </summary>
		// void OnHosted ();

	}


	public class Menu : NotifyPropertyChanged, IMenu, IUIParent<IMenu>
	{
		/// <summary>
		///		the key for view locator lookup .
		/// </summary>
		// private string _viewKey;

		/// <summary>
		///		the display string of this view .
		/// </summary>
		private string _text;

		/// <summary>
		///		 image file, as a thumbnail .
		/// </summary>
		private string _icon;

		/// <summary>
		///		the Shut-Cut .
		/// </summary>
		private string _hotKey;

		/// <summary>
		///		the parent window of this view .
		/// </summary>
		private object _Parent;

		/// <summary>
		///		the sub menu item(s) .
		/// </summary>
		private IBindableCollection<IMenu> m_children = new BindableCollection<IMenu>();


		/// <summary>
		///		indicates if this view is enabled .
		/// </summary>
		private bool _isEnabled;

		/// <summary>
		///		indicates if this is visiable .
		/// </summary>
		private bool _visibility = true;

		/// <summary>
		///		Is a checkable menu item ?
		/// </summary>
		private bool _canCheck = false;

		/// <summary>
		///		Is this item checked ?
		/// </summary>
		private bool _isChecked = false;

		/// <summary>
		///		is this a seperator ?
		/// </summary>
		private bool _isDivider = false;

		/// <summary>
		///		extra user-defined data block .
		/// </summary>
		private object _userData;


		/// <summary>
		/// 
		/// </summary>
		private readonly Action<Menu> _execute;
		
		/// <summary>
		/// 
		/// </summary>
		private readonly Func<Boolean> _canExecute;


	

		/// <summary>
		///		c;tor
		/// </summary>
		public Menu ( string text, Action<Menu> execute, Func<bool> canExecute = null )
		{
			this._text = text;

			this._execute = execute ?? ( (i) => { } );
			this._canExecute = canExecute ?? (() => IsEnabled);

		}



		// hidden .
		IEnumerable<IMenu> IUIParent<IMenu>.GetChildren()
		{
			return this.m_children; 
		}
		IEnumerable IUIParent.GetChildren()
		{
			return this.m_children;
		}

		/// <summary>
		/// 
		/// </summary>
		public IBindableCollection<IMenu> Children
		{
			get { return this.m_children; }
		}


		public string KeyText
		{
			get
			{
				return this._text;
			}
			set
			{
				this._text = value;
				this.RaisePropertyChanged(() => this.KeyText);
			}
		}
        /// <summary>
        ///		Gets or sets display text, is used for Headers controls such as TabControl
        /// </summary>
        public string DisplayText
        {
            get
            {
                return this._text;
            }
            set
            {
                this._text = value;
                this.RaisePropertyChanged( () => this.DisplayText );
            }
        }

		/// <summary>
		///		True if this view has an icon .
		/// </summary>
		public bool HasIcon
		{
			get
			{
				return !string.IsNullOrEmpty(this._icon);
			}
		}

		public string Icon
		{
			get 
			{
				return this._icon; 
			}
			set 
			{ 
				this._icon = value;
				this.RaisePropertyChanged ( () => Icon );
			}
		}

		public string HotKey
		{
			get 
			{ 
				return this._hotKey; 
			}
			set 
			{
				this._hotKey = value;
				this.RaisePropertyChanged ( () => HotKey ); 
			}
		}

		public object Parent
		{
			get
			{
				return this._Parent;
			}
			set
			{
				this._Parent = value;
				this.RaisePropertyChanged(() => Parent);
			}
		}
		public bool Visibility
		{
			get 
			{
				return this._visibility; 
			}
			set 
			{
				this._visibility = value;
				this.RaisePropertyChanged(() => Visibility); 
			}
		}

		public bool CanCheck
		{
			get
			{
				return this._canCheck;
			}
			set
			{
				this._canCheck = value;
				this.RaisePropertyChanged( () => CanCheck );
			}
		}
		
		public bool IsChecked
		{
			get
			{
				return this._isChecked;
			}
			set
			{
				this._isChecked = value;
				this.RaisePropertyChanged(() => IsChecked);
			}
		}

		public bool IsDivider
		{
			get
			{
				return this._isDivider;
			}
			protected set
			{
				this._isDivider = value;
				this.RaisePropertyChanged(() => IsDivider);
			}
		}

		/// <summary>
		///      context data
		/// </summary>
		public object UserData
		{
			get
			{
				return this._userData;
			}
			set
			{
				this._userData = value;
				this.RaisePropertyChanged(() => UserData);
			}
		}


		/// <summary>
		///		event raised after enabling occurs
		/// </summary>
		public event EventHandler<UIEnabledEventArgs> Enabled = delegate { };

		/// <summary>
		///		event raised after disabled
		/// </summary>
		public event EventHandler<UIDisabledEventArgs> Disabled = delegate { };

		/// <summary>
		///		event raised before disabling 
		/// </summary>
		public event EventHandler<UIDisabledEventArgs> AttemptingDisabled = delegate { };


		/// <summary>
		/// 
		/// </summary>
		public bool IsEnabled
		{
			get
			{
				return this._isEnabled;
			}
			set
			{
				this._isEnabled = value;
				this.RaisePropertyChanged(() => this.IsEnabled);
			}
		}

		
		public virtual void SetEnabled ()
		{
			if ( !_isEnabled )
			{
				this._isEnabled = true;
				
				// handler .
				OnEnabled ();

				// event .
				if ( this.Enabled != null)
					this.Enabled ( this, new UIEnabledEventArgs { WasLoaded = false });
			}
		}

		public virtual void SetDisabled ( bool close )
		{
			if ( this._isEnabled )
			{
				// about to de ...
				if ( this.AttemptingDisabled != null)
					this.AttemptingDisabled( this, new UIDisabledEventArgs { WasClosed = close });

				this._isEnabled = false;

				// handler .
				this.OnDisabled( close );

				// ok, raise event .
				if ( this.Disabled != null)
					this.Disabled ( this, new UIDisabledEventArgs { WasClosed = close });
			}

		}


		protected virtual void OnEnabled ()
		{
		}
		protected virtual void OnDisabled ( bool close ) 
		{ 
		}



		/// <summary>
		///		
		/// </summary>
		public virtual void Execute ()
		{
			this._execute ( this);
		}

		/// <summary>
		/// 
		/// </summary>
		public virtual bool CanExecute 
		{
			get { return this._canExecute(); }
		}



		
	}


	public interface IMenuMetadata
	{
		/// <summary>
		///		Gets the identifier string of this menu part .
		/// </summary>
		string MenuID { get; }

		/// <summary>
		///		Gets the root(category) menu part of this .
		/// </summary>
		string MenuRoot { get; }

		/// <summary>
		///		Gets the previous menu part .
		/// </summary>
		string MenuPrev { get; }

		/// <summary>
		///		Gets the next menu part .
		/// </summary>
		string MenuNext { get; }
	}

	// This metadata .
	[MetadataAttribute]
	// Usage .
	[AttributeUsage( AttributeTargets.Class, AllowMultiple = false)]
	public class MenuExportAttribute : ExportAttribute, IMenuMetadata
	{

		public MenuExportAttribute ()  
			: base( typeof(IMenu) ) 
		{ 
		}

		public MenuExportAttribute ( Type contractType )
			: base( contractType) 
		{ 
		}

		/// <summary>
		///		Gets the identifier string of this menu part .
		/// </summary>
		public string MenuID { get; set; }

		/// <summary>
		///		Gets the root(category) menu part of this .
		/// </summary>
		public string MenuRoot { get; set; }

		/// <summary>
		///		Gets the previous menu part .
		/// </summary>
		public string MenuPrev { get; set; }

		/// <summary>
		///		Gets the next menu part .
		/// </summary>
		public string MenuNext { get; set; }


	}

}
